package com.uinnova.product.eam.service.cj.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.enums.ResultCodeEnum;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.model.cj.domain.*;
import com.uinnova.product.eam.model.cj.enums.PlanStatusEnum;
import com.uinnova.product.eam.model.cj.enums.TableContentTypeEnum;
import com.uinnova.product.eam.model.cj.vo.*;
import com.uinnova.product.eam.model.dmv.ClassDefinitionVO;
import com.uinnova.product.eam.service.EamCategorySvc;
import com.uinnova.product.eam.service.IOperateSettingService;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.service.cj.dao.*;
import com.uinnova.product.eam.service.cj.service.DeliverableTemplateService;
import com.uinnova.product.eam.service.exception.BusinessException;
import com.uinnova.product.vmdb.comm.model.ci.CCcCiClass;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.util.ESUtil;
import com.uino.service.cmdb.microservice.impl.CIClassSvc;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


@Service
@Slf4j
public class DeliverableTemplateServiceImpl implements DeliverableTemplateService {

    /**
     * 模板状态 0:禁用 1:设计中 变更 2:设计中 草稿 3:再用 已发布 4:再用 已屏蔽 5:停用 已发布
     */
    private static final List<Integer> DELIVERABLE_TYPE = new ArrayList<>(Arrays.asList(0,2,3,4,5));

    @Autowired
    private DeliverableTemplateDao deliverableTemplateDao;
    @Autowired
    private TemplateTypeDao templateTypeDao;
    @Resource
    private PlanDesignInstanceDao planDesignInstanceDao;

    @Resource
    private PlanTemplateChapterDao planTemplateChapterDao;

    @Resource
    private PlanTemplateChapterDataDao planTemplateChapterDataDao;

    @Resource
    private IUserApiSvc userApiSvc;

    @Resource
    private CIClassSvc clsSvc;

    @Resource
    private IOperateSettingService operateSettingService;

    @Resource
    private EamCategorySvc categorySvc;
    @Autowired
    private BmConfigSvc bmConfigSvc;

    @Override
    public Long saveOrUpdateDlvrTemplate(DeliverableTemplate cdt) {

        if (cdt.getStatus() != null && !DELIVERABLE_TYPE.contains(cdt.getStatus())) {
            throw new BinaryException("模板状态只能在指定的枚举类型里面");
        }

        if (!CollectionUtils.isEmpty(cdt.getBindAssetList())) {
            for (BindAssetVo bindAssetVo : cdt.getBindAssetList()) {
                if (bindAssetVo.getClassId() != null) {
                    CcCiClassInfo ccCiClassInfo = clsSvc.queryClassInfoById(bindAssetVo.getClassId());
                    if (null == ccCiClassInfo || null == ccCiClassInfo.getCiClass()) {
                        throw new BinaryException("绑定资产不存在，请重新配置绑定资产");
                    }
                }
                if (StringUtils.isBlank(bindAssetVo.getClassName())) {
                    CcCiClassInfo ccCiClassInfo = clsSvc.queryClassInfoById(bindAssetVo.getClassId());
                    String className = ccCiClassInfo.getCiClass().getClassName();
                    bindAssetVo.setClassName(className);
                }
            }
        }

        //下面是删除模板的时候校验模板下面是否有方案，以后添加版本的时候需要删除这段代码
        if (cdt.getStatus() != null && cdt.getStatus() == 0) {
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(QueryBuilders.termQuery("templateId",cdt.getId()));
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("status.keyword","deleted"));
            List<PlanDesignInstance> planDesignInstances = planDesignInstanceDao.getListByQuery(boolQueryBuilder);
            boolean flag = CollectionUtils.isEmpty(planDesignInstances);
            if (!flag) {
                return -1L;
            }
        }
        //如果是发布，需要校验一下此模板之前是否发布
        if (cdt.getStatus() != null && cdt.getStatus() == 3) {
            DeliverableTemplate deliverableTemplate = deliverableTemplateDao.getById(cdt.getId());
            if (deliverableTemplate.getStatus() == 3) {
                throw new BusinessException("模板已经发布，不能再发布");
            }
        }
        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();

        //校验交付物模板名称是否重复
        Long id = cdt.getId();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (id != null) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", id));
        }
        boolQueryBuilder.must(QueryBuilders.termQuery("templateName.keyword",cdt.getTemplateName()));
        boolQueryBuilder.mustNot(QueryBuilders.termQuery("status",0));
        List<DeliverableTemplate> dlvrList = deliverableTemplateDao.getListByQuery(boolQueryBuilder);
        if (!CollectionUtils.isEmpty(dlvrList)) {
            throw new BusinessException(ResultCodeEnum.DUPLICATE_NAME);
        }
        //保存或更新
        if (BinaryUtils.isEmpty(cdt.getId())) {
            cdt.setId(ESUtil.getUUID());
            cdt.setCreateTime(BinaryUtils.getNumberDateTime());
            cdt.setCreator(currentUserInfo.getLoginCode());
            cdt.setStatus(2);
        } else {
            DeliverableTemplate template = deliverableTemplateDao.getById(cdt.getId());
            if (template != null) {
                if(BinaryUtils.isEmpty(cdt.getAssetsDirId()) && BinaryUtils.isEmpty(cdt.getStatus())){
                    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
                    boolQuery.must(QueryBuilders.termQuery("id", template.getId()));
                    String script = "ctx._source.assetsDirId=null;ctx._source.echoDirName=null;";
                    boolean suc = deliverableTemplateDao.updateByQuery(boolQuery, script, true);
                }
                cdt.setCreateTime(template.getCreateTime());
                cdt.setCreator(template.getCreator());
            }
        }
        cdt.setModifier(currentUserInfo.getLoginCode());
        cdt.setModifyTime(BinaryUtils.getNumberDateTime());
        Long result = deliverableTemplateDao.saveOrUpdate(cdt);

        if (Objects.equals(cdt.getStatus(), 5) || Objects.equals(cdt.getStatus(), 3)) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.termQuery("planTemplateId", result));
            query.must(QueryBuilders.termQuery("status", 1));
            List<PlanTemplateChapter> chapterList = planTemplateChapterDao.getListByQuery(query);
            List<PlanTemplateChapter> newChapterList = new ArrayList<>();
            for (PlanTemplateChapter chapter : chapterList) {
                if (chapter == null) {
                    continue;
                }
                if (!CollectionUtils.isEmpty(chapter.getPlanTemplateIntroduceChapterVoList())) {
                    List<PlanTemplateIntroduceChapterVo> introduceList = chapter.getPlanTemplateIntroduceChapterVoList();
                    for (PlanTemplateIntroduceChapterVo introduceVo : introduceList) {
                        if (Objects.equals(cdt.getStatus(), 5)) {
                            introduceVo.setDelete(0);
                        } else if (Objects.equals(cdt.getStatus(), 3)) {
                            introduceVo.setDelete(1);
                        }

                    }
                }
                if (Objects.equals(cdt.getStatus(), 5)) {
                    chapter.setIntroduceButton(0);
                } else if (Objects.equals(cdt.getStatus(), 3)) {
                    chapter.setIntroduceButton(1);
                }
                newChapterList.add(chapter);
            }
            planTemplateChapterDao.saveOrUpdateBatch(newChapterList);
        }
        return result;

    }

    @Override
    public Page<DlvrTemplateVO> getDlvrTemplateList(DlvrTemplateReq queryBean) {
        CSysUser user = new CSysUser();
        user.setLoginCodeEqual(SysUtil.getCurrentUserInfo().getLoginCode());
        List<SysUser> sysUser = userApiSvc.getSysUserByCdt(user);
        String icon = sysUser.get(0).getIcon();


        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        if (queryBean.getPageNum() == null) {
            queryBean.setPageNum(1);
        }
        if (queryBean.getPageSize() == null) {
            queryBean.setPageSize(20);
        }
        if (queryBean.getTemplateName() != null) {
            List<SysUser> userLike = userApiSvc.getUserInfoByName(queryBean.getTemplateName().trim());
            BoolQueryBuilder shouldQuery = QueryBuilders.boolQuery();
            if(!CollectionUtils.isEmpty(userLike)){
                Set<String> nameLists = userLike.stream().map(SysUser::getLoginCode).collect(Collectors.toSet());
                shouldQuery.should(QueryBuilders.termsQuery("creator.keyword", nameLists));
            }
            shouldQuery.should(QueryBuilders.wildcardQuery("creator.keyword", "*" + queryBean.getTemplateName().trim() + "*"));
            shouldQuery.should(QueryBuilders.wildcardQuery("templateName.keyword", "*" + queryBean.getTemplateName().trim() + "*"));
            boolQueryBuilder.must(shouldQuery);
        }
        if (queryBean.getStatus() == null) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("status",0));
        }
        if (!CollectionUtils.isEmpty(queryBean.getStatus())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("status",queryBean.getStatus()));
        }

        if (queryBean.getProposalType() != null) {
            boolQueryBuilder.must(QueryBuilders.termQuery("proposalType",queryBean.getProposalType()));
        }

        List<SortBuilder<?>> sorts = new ArrayList<>();
        sorts.add(SortBuilders.fieldSort("modifyTime").order(SortOrder.DESC));
        Page<DeliverableTemplate> pageInfo = deliverableTemplateDao.getSortListByQuery(queryBean.getPageNum(), queryBean.getPageSize(), boolQueryBuilder, sorts);
        List<DeliverableTemplate> data = pageInfo.getData();
        List<TemplateType> listByCdt = templateTypeDao.getListByCdt(new TemplateType());
        if (CollectionUtils.isEmpty(listByCdt)) {
            return new Page<>();
        }
        //查询模板被引用的数量
        List<Long> template = data.stream().map(DeliverableTemplate :: getId).collect(Collectors.toList());
        Map<Long, Long> planDesignMap = new HashMap<>();
        BoolQueryBuilder planDesignInstanceQueryBuilder = QueryBuilders.boolQuery();
        planDesignInstanceQueryBuilder.must(QueryBuilders.termsQuery("templateId.keyword",template));
        List<PlanDesignInstance> planDesignList = planDesignInstanceDao.getListByQuery(planDesignInstanceQueryBuilder);
        if (!CollectionUtils.isEmpty(planDesignList)) {
            planDesignMap = planDesignList.stream().collect(Collectors.groupingBy(item -> item.getTemplateId(), Collectors.counting()));
        }



        Map<Long, TemplateType> resultMap = listByCdt.stream().collect(Collectors.toMap(TemplateType :: getId, item -> item));
        List<DlvrTemplateVO> dlvrTemplateVOS = new ArrayList<>();
        for (DeliverableTemplate deliverableTemplate : data) {
            TemplateType templateType = resultMap.get(deliverableTemplate.getProposalType());
            if (templateType == null) {
                continue;
            }
            DlvrTemplateVO dlvrTemplateVO = BeanUtil.copyProperties(deliverableTemplate, DlvrTemplateVO.class);
            dlvrTemplateVO.setProposalName(templateType.getTypeName());
            if (planDesignMap.get(deliverableTemplate.getId()) != null) {
                Long count = planDesignMap.get(deliverableTemplate.getId());
                dlvrTemplateVO.setQuoteNum(count.intValue());
            }
            dlvrTemplateVO.setIcon(icon);
            dlvrTemplateVOS.add(dlvrTemplateVO);
        }
        String[] loginCodes = dlvrTemplateVOS.stream().map(DlvrTemplateVO::getCreator).distinct().toArray(String[]::new);
        if (loginCodes != null && loginCodes.length > 0) {
            CSysUser cSysUser = new CSysUser();
            cSysUser.setLoginCodes(loginCodes);
            List<SysUser> sysUserByCdt = userApiSvc.getSysUserByCdt(cSysUser);
            Map<String, String> userMap = sysUserByCdt.stream().collect(Collectors.toMap(item -> item.getLoginCode(), item -> item.getUserName(), (v1, v2) -> v2));
            for (DlvrTemplateVO dlvrTemplateVO : dlvrTemplateVOS) {
                String userName = userMap.get(dlvrTemplateVO.getCreator());
                dlvrTemplateVO.setCreatorName(userName);
            }
        }

        Page<DlvrTemplateVO> result = new Page<>();
        result.setData(dlvrTemplateVOS);
        result.setPageNum(pageInfo.getPageNum());
        result.setPageSize(pageInfo.getPageSize());
        result.setTotalRows(pageInfo.getTotalRows());
        result.setTotalPages(pageInfo.getTotalPages());
        return result;
    }
    @Override
    public DlvrTemplateVO getDlvrTemplateById(Long id) {
        DeliverableTemplate result = deliverableTemplateDao.getById(id);
        if (BinaryUtils.isEmpty(result)) {
            return null;
        }
        Assert.isTrue(result.getProposalType() != null, "名称重复");
        TemplateType templateType = templateTypeDao.getById(result.getProposalType());
        if (result.getAssetsDirId() != null) {
            String echoName = categorySvc.getDirPathName(result.getAssetsDirId(), LibType.DESIGN);
            if (BinaryUtils.isEmpty(echoName)) {
                result.setAssetsDirId(-1L);
            }
            result.setEchoDirName(echoName);
            deliverableTemplateDao.saveOrUpdate(result);
        }
        DlvrTemplateVO dlvrTemplateVO = BeanUtil.copyProperties(result, DlvrTemplateVO.class);
        dlvrTemplateVO.setProposalName(templateType.getTypeName());
        return dlvrTemplateVO;
    }

    @Override
    public Long createOrUpdateTemplateType(List<TemplateType> templateTypes) {
        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();

       /* //校验交付物模板名称是否重复
        String id = templateType.getId();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (id != null) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", id));
        }
        boolQueryBuilder.must(QueryBuilders.termQuery("typeName.keyword",templateType.getTypeName()));
        List<TemplateType> typeList = templateTypeDao.getListByQuery(boolQueryBuilder);
        if (typeList.size() >= 1) {
            throw new BusinessException(ResultCodeEnum.DUPLICATE_NAME);
        }
        //保存或更新
        if (BinaryUtils.isEmpty(templateType.getId())) {
            templateType.setId(String.valueOf(uuid));
            templateType.setCreator(currentUserInfo.getLoginCode());
            templateType.setStatus(0);
        }*/
       //批量保存交付物模板类型，保存之后需要清空存量数据
        List<Long> ids = templateTypes.stream().filter(item -> item.getId() != null).map(TemplateType :: getId).collect(Collectors.toList());

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.mustNot(QueryBuilders.termsQuery("id",ids.toArray()));
        templateTypeDao.deleteByQuery(boolQueryBuilder,true);
        for (TemplateType templateType : templateTypes) {
            if (BinaryUtils.isEmpty(templateType.getId())) {
                long uuid = ESUtil.getUUID();
                templateType.setId(uuid);
                templateType.setCreator(currentUserInfo.getLoginCode());
            }
        }
        Integer result = templateTypeDao.saveOrUpdateBatch(templateTypes);
        return Long.valueOf(result);
    }

    @Override
    public List<TemplateType> getListTemplateType() {
        List<TemplateType> result = templateTypeDao.getListByCdt(new TemplateType());
        if (result == null || result.isEmpty()) {
            return new ArrayList<>();
        }else{
            List<TemplateType> resultList = result.stream().sorted(Comparator.comparing(TemplateType :: getSort)).collect(Collectors.toList());
            return resultList;
        }
    }

    @Override
    public Boolean deleteTemplateType(Long id) {
        TemplateType templateType = templateTypeDao.getById(id);
        templateType.setStatus(1);
        Long result = templateTypeDao.saveOrUpdate(templateType);
        return result != null;
    }

    @Override
    public Boolean validDelete(Long id) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("proposalType",id));
        boolQueryBuilder.mustNot(QueryBuilders.termQuery("status",0));
        List<DeliverableTemplate> templateList = deliverableTemplateDao.getListByQuery(boolQueryBuilder);
        return CollectionUtils.isEmpty(templateList);
    }

    @Override
    public List<DlvrTemplateDTO> getReleaseTemplateList(DlvrTemplateReq dlvrTemplateReq) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (dlvrTemplateReq.getProposalType() != null) {
            boolQueryBuilder.must(QueryBuilders.termQuery("proposalType",dlvrTemplateReq.getProposalType()));
        }
        // 已发布状态
        boolQueryBuilder.must(QueryBuilders.termsQuery("status", Lists.newArrayList(3, 5)));
        List<SortBuilder<?>> sorts = new ArrayList<>();
        SortBuilder<?> statusSort = SortBuilders.fieldSort("status").order(SortOrder.ASC);
        SortBuilder<?> modifyTimeSort = SortBuilders.fieldSort("modifyTime").order(SortOrder.DESC);
        sorts.add(statusSort);
        sorts.add(modifyTimeSort);
        long count = deliverableTemplateDao.countByCondition(boolQueryBuilder);
        Page<DeliverableTemplate> templatePage = deliverableTemplateDao.getSortListByQuery(1, (int) count, boolQueryBuilder, sorts);
        if (templatePage == null || CollectionUtils.isEmpty(templatePage.getData())) {
            return new ArrayList<>();
        }
        List<DeliverableTemplate> templateList = templatePage.getData();

        //查询方案的时候 校验如果模板配置了发布位置 查看仓库是否删除 如果删除 清空方案里面的发布位置
        List<Long> assertDirIds = templateList.stream().map(DeliverableTemplate::getAssetsDirId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<EamCategory> dirList = categorySvc.getByIds(assertDirIds, LibType.DESIGN);
        Map<Long, String> dirPathNameMap = categorySvc.getDirPathName(assertDirIds, LibType.DESIGN);
        for (DeliverableTemplate each : templateList) {
            if (each.getAssetsDirId() != null && !dirPathNameMap.containsKey(each.getAssetsDirId())) {
                each.setAssetsDirId(-1L);
                each.setEchoDirName("");
            }else{
                each.setEchoDirName(dirPathNameMap.get(each.getAssetsDirId()));
            }
        }

        Map<String, Long> archReviewConf = getArchReviewConf();
        Long archReviewTypeId = archReviewConf.get("typeId");
        Long archReviewProjectClassId = archReviewConf.get("projectClassId");
        List<DlvrTemplateDTO> result = templateList.stream().map(item -> {
            DlvrTemplateDTO dlvrTemplateDTO = new DlvrTemplateDTO();
            dlvrTemplateDTO.setId(item.getId());
            dlvrTemplateDTO.setTemplateName(item.getTemplateName());
            dlvrTemplateDTO.setTypeId(item.getProposalType());
            dlvrTemplateDTO.setAssetsDirId(item.getAssetsDirId());
            dlvrTemplateDTO.setEchoDirName(item.getEchoDirName());
            dlvrTemplateDTO.setDirType(item.getDirType());
            dlvrTemplateDTO.setStatus(item.getStatus());
            dlvrTemplateDTO.setDomainDirId(item.getDomainDirId());
            dlvrTemplateDTO.setPlanBindProject(Boolean.FALSE);
            if (!CollectionUtils.isEmpty(item.getBindAssetList())) {
                dlvrTemplateDTO.setBindAssetList(item.getBindAssetList());
                boolean planBindProject = archReviewTypeId.equals(item.getProposalType())
                        && archReviewProjectClassId.equals(item.getBindAssetList().get(0).getClassId());
                dlvrTemplateDTO.setPlanBindProject(planBindProject);
            }
            return dlvrTemplateDTO;
        }).collect(Collectors.toList());

        return result;
    }

    private Map<String, Long> getArchReviewConf() {
        String configJson = bmConfigSvc.getConfigType("AXEA_CONFIG");
        if (StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        JSONObject conf = JSON.parseObject(configJson);
        if (conf == null) {
            throw new BinaryException("未查询到国投分类映射配置，请联系管理员");
        }
        String archReviewTemplateTypeName = conf.getString("archReviewTemplateTypeName");
        if (StringUtils.isBlank(archReviewTemplateTypeName)) {
            throw new BinaryException("未查询到国投架构方案模板类型配置，请联系管理员");
        }
        TemplateType templateType = this.getTemplateTypeByName(archReviewTemplateTypeName);
        if (templateType == null) {
            log.error("未查询到国投架构方案模板类型配置[archReviewTemplateTypeName:{}]，请联系管理员", archReviewTemplateTypeName);
            throw new BinaryException("未查询到国投架构方案模板类型配置，请联系管理员");
        }
        String axeaClassMapping = conf.getString("classMapping");
        if (StringUtils.isBlank(axeaClassMapping)) {
            throw new BinaryException("未查询到国投项目分类映射配置，请联系管理员");
        }
        JSONObject axeaClassConf = JSONObject.parseObject(axeaClassMapping);
        String projectClassCode = axeaClassConf.getString("projectClassCode");
        if (StringUtils.isBlank(projectClassCode)) {
            throw new BinaryException("未查询到国投项目分类映射配置，请联系管理员");
        }
        String[] projectClassCodes = new String[]{projectClassCode};
        CCcCiClass projectCdt = new CCcCiClass();
        projectCdt.setClassCodes(projectClassCodes);
        List<CcCiClassInfo> projectCiClassInfos = clsSvc.queryClassByCdt(projectCdt);
        if (CollectionUtils.isEmpty(projectCiClassInfos)) {
            String msg = "未查询到国投项目分类[projectClassCode:".concat(projectClassCode).concat("]，请联系管理员");
            throw new BinaryException(msg);
        }
        Map<String, Long> archReviewConf = new ConcurrentHashMap<>();
        archReviewConf.put("typeId", templateType.getId());
        archReviewConf.put("projectClassId", projectCiClassInfos.get(0).getCiClass().getId());
        return archReviewConf;
    }

    @Override
    public Boolean deleteDraftTemplate(Long templateId) {
        // 删除交付物模板
        Integer result = deliverableTemplateDao.deleteById(templateId);
        // 删除章节
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("planTemplateId", templateId));
        queryBuilder.must(QueryBuilders.termQuery("status", 1));
        List<PlanTemplateChapter> chapterList = planTemplateChapterDao.getListByQuery(queryBuilder);
        if (!CollectionUtils.isEmpty(chapterList)) {
            chapterList.forEach(templateChapter -> {
                templateChapter.setStatus(0);
            });
            planTemplateChapterDao.saveOrUpdateBatch(chapterList);
        }
        // 删除模板数据
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("planTemplateId", templateId));
        planTemplateChapterDataDao.deleteByQuery(boolQueryBuilder, true);
        return result>=0;
    }

    @Override
    public List<TemplateType> getListShowTemplateType() {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.mustNot(QueryBuilders.termQuery("status.keyword", PlanStatusEnum.deleted));
        List<PlanDesignInstance> planDesignInstanceList = planDesignInstanceDao.getListByQuery(boolQueryBuilder);
        if (!CollectionUtils.isEmpty(planDesignInstanceList)) {
            List<Long> typeIds = planDesignInstanceList.stream().map(PlanDesignInstance::getTypeId).collect(Collectors.toList());
            List<Long> distinctTypeIds = typeIds.stream().distinct().filter(typeId -> typeId != null).collect(Collectors.toList());
            BoolQueryBuilder resultBuilder = QueryBuilders.boolQuery();
            resultBuilder.must(QueryBuilders.termsQuery("id",distinctTypeIds));
            return templateTypeDao.getListByQuery(resultBuilder);
        }
        return new ArrayList<>();
    }

    @Override
    public Boolean copyTemplateInfoById(Long templateId,String templateName) {
        SysUser user = SysUtil.getCurrentUserInfo();
        long copyTemplateId = ESUtil.getUUID();
        DeliverableTemplate deliverableTemplate = deliverableTemplateDao.getById(templateId);
        deliverableTemplate.setId(copyTemplateId);
        if (templateName!=null) {
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(QueryBuilders.termQuery("templateName.keyword", templateName));
            List<DeliverableTemplate> listByQuery = deliverableTemplateDao.getListByQuery(boolQueryBuilder);
            if (!CollectionUtils.isEmpty(listByQuery)) {
                throw new BusinessException("复制修改的模板名称重复,请重新输入",templateName);
            }
            deliverableTemplate.setTemplateName(templateName);
        }else{
            String copyTemplateName = getCopyTemplateName(deliverableTemplate);
            if (copyTemplateName.length() > 50) {
                throw new BusinessException("复制的交付物模板名称超过50",copyTemplateName);
            }
            deliverableTemplate.setTemplateName(getCopyTemplateName(deliverableTemplate));
        }
        deliverableTemplate.setStatus(2);
        deliverableTemplate.setCreateTime(BinaryUtils.getNumberDateTime());
        deliverableTemplate.setModifyTime(BinaryUtils.getNumberDateTime());
        deliverableTemplate.setCreator(user.getLoginCode());
        deliverableTemplate.setModifier(user.getLoginCode());
        deliverableTemplateDao.saveOrUpdate(deliverableTemplate);
        //根据交付物模板查找下面所有的章节信息
        List<PlanTemplateChapter> planTemplateChapters = findAllPlanTemplateChapter(templateId);
        //复制所有章节信息（包括子章节）
        Map<Long,Long> copyMap = new HashMap<>();
        copyChapter(planTemplateChapters,copyTemplateId,copyMap);
        //复制交付物模板完成
        return true;
    }

    @Override
    public List<PlanTemplateChapterTreeVo> getTemplateChapterList(Long templateId) {
        List<PlanTemplateChapter> planTemplateChapters = planTemplateChapterDao.getListByQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("planTemplateId", templateId)));
        DeliverableTemplate template = deliverableTemplateDao.getById(templateId);
        List<PlanTemplateChapter> templateChapters = planTemplateChapters.stream().filter(item -> item.getStatus() == 1).collect(Collectors.toList());
        List<PlanTemplateChapter> parentChapter = templateChapters.stream().filter(item -> item.getParentId() == 0l).sorted(Comparator.comparing(PlanTemplateChapter :: getSortNum)).collect(Collectors.toList());
        List<PlanTemplateChapterTreeVo> copyData = EamUtil.copy(parentChapter, PlanTemplateChapterTreeVo.class);
        findChildChapter(planTemplateChapters,copyData,template.getTemplateName(),"","");
        return copyData;
    }

    @Override
    public DeliverableTemplate getDeliverableTemplateById(Long id) {
        return deliverableTemplateDao.getById(id);
    }


    @Override
    public  List<DeliverableTemplate> getPublishTemplateInfos() {
        //获取已发布的模板
        DeliverableTemplate deliverableTemplate = new DeliverableTemplate();
        deliverableTemplate.setStatus(3);
        List<SortBuilder<?>> sorts = new ArrayList<>();
        FieldSortBuilder modifyTimeSortBuilder = SortBuilders.fieldSort("modifyTime").order(SortOrder.DESC);
        sorts.add(modifyTimeSortBuilder);
        return deliverableTemplateDao.getSortListByCdt(deliverableTemplate, sorts);
    }

    private void findChildChapter(List<PlanTemplateChapter> planTemplateChapters, List<PlanTemplateChapterTreeVo> copyData,String templateName,String chapterName,String chapterId) {
        if (CollectionUtils.isEmpty(copyData)) {
            return;
        }
        for (PlanTemplateChapterTreeVo copyDatum : copyData) {
            List<PlanTemplateChapter> childData = planTemplateChapters.stream().filter(item -> item.getParentId().equals(copyDatum.getId()) && item.getStatus() == 1).sorted(Comparator.comparing(PlanTemplateChapter :: getSortNum)).collect(Collectors.toList());
            List<PlanTemplateChapterTreeVo> childCopyData = EamUtil.copy(childData, PlanTemplateChapterTreeVo.class);
            String currentChapterIdPath = "";
            String currentPlanChapterName = "";
            if (StringUtils.isBlank(chapterId)) {
                currentChapterIdPath = ""+copyDatum.getId();
            }else{
                currentChapterIdPath = chapterId + "/" +  copyDatum.getId();
            }
            copyDatum.setChapterIdPath(currentChapterIdPath);

            if (StringUtils.isBlank(chapterName)) {
                currentPlanChapterName = templateName + " /" + copyDatum.getChapterName();
            }else{
                currentPlanChapterName = chapterName +"/"+ copyDatum.getChapterName();
            }
            copyDatum.setPlanAndChapterName(currentPlanChapterName);
            copyDatum.setChild(childCopyData);
            findChildChapter(planTemplateChapters,childCopyData,templateName,currentPlanChapterName,currentChapterIdPath);
        }
    }

    @Override
    public List<TableContentTypeVo> findTableContentTypeList(Long templateId) {
        List<TableContentTypeVo> typeList = TableContentTypeEnum.getTypeList();
        if (CollectionUtils.isEmpty(typeList)) {
            return Collections.emptyList();
        }
        DeliverableTemplate deliverableTemplate = deliverableTemplateDao.getById(templateId);
        if (deliverableTemplate == null) {
            throw new BusinessException("获取方案模板异常!");
        }
        if (CollectionUtils.isEmpty(deliverableTemplate.getBindAssetList())) {
            typeList = typeList.stream().map(type -> {
                if (Objects.equals(type.getType(), TableContentTypeEnum.BIND_ASSET.getType())) {
                    type.setStatus(0);
                }
                return type;
            }).collect(Collectors.toList());
        }
        return typeList;
    }

    @Override
    public List<ClassDefinitionVO> findClassDefinitionList(Long templateId) {
        DeliverableTemplate deliverableTemplate = deliverableTemplateDao.getById(templateId);
        if (deliverableTemplate == null) {
            throw new BusinessException("获取方案模板异常!");
        }
        if (!CollectionUtils.isEmpty(deliverableTemplate.getBindAssetList())) {
            BindAssetVo bindAssetVo = deliverableTemplate.getBindAssetList().get(0);
            if (bindAssetVo.getClassId() != null) {
                List<ClassDefinitionVO> classDefinitionList = operateSettingService.findClassDefinitionList();
                if (!CollectionUtils.isEmpty(classDefinitionList)) {
                    classDefinitionList = classDefinitionList.stream().filter(classDefinitionVO ->
                            Objects.equals(classDefinitionVO.getClassSet().getClassId(), bindAssetVo.getClassId()))
                            .collect(Collectors.toList());
                }
                return classDefinitionList;
            }

        }
        return Collections.emptyList();
    }

    private String getCopyTemplateName(DeliverableTemplate deliverableTemplate) {
//        StringBuilder stringBuilder = new StringBuilder();
//        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("templateName.keyword",deliverableTemplate.getTemplateName()));
//        List<DeliverableTemplate> deliverableTemplates = deliverableTemplateDao.getListByQuery(boolQueryBuilder);
//        for (DeliverableTemplate template : deliverableTemplates) {
//            stringBuilder.append("-copy");
//        }
//        return deliverableTemplate.getTemplateName()+stringBuilder.toString();

        // 之前可能存在已经复制的重名数据 需要手动删除
        // 每次复制时添加 -copy后缀 存在 -copy后缀在后面追加 2.3.4.....
        return checkName(deliverableTemplate.getTemplateName());
    }


    public String checkName(String name) {
        name = name + "-copy";
        List<DeliverableTemplate> listByQuery = deliverableTemplateDao.getListByQuery(QueryBuilders.termQuery("templateName.keyword", name));
        if (CollectionUtils.isEmpty(listByQuery)) {
            return name;
        }
        for (int i = 2; i <= 1000; i ++) {
            List<DeliverableTemplate> listByQueryNum = deliverableTemplateDao.getListByQuery(QueryBuilders.termQuery("templateName.keyword", name + i));
            if (CollectionUtils.isEmpty(listByQueryNum)) {
                return name + i;
            }
        }
        return name;
    }

    /**
     * 先把层级是1章节进行复制
     * @param planTemplateChapters
     * @param copyTemplateId
     * @param copyMap
     */
    private void copyChapter(List<PlanTemplateChapter> planTemplateChapters, long copyTemplateId, Map<Long, Long> copyMap) {
        List<PlanTemplateChapter> parentPlanTemplateChapters = planTemplateChapters.stream().filter(item -> item.getLevel() == 1).collect(Collectors.toList());

        for (PlanTemplateChapter planTemplateChapter : parentPlanTemplateChapters) {
            long copyChapterId = ESUtil.getUUID();
            Long planTemplateId = planTemplateChapter.getPlanTemplateId();
            Long chapterId = planTemplateChapter.getId();
            copyMap.put(chapterId,copyChapterId);

            List<PlanTemplateIntroduceChapterVo> planTemplateIntroduceChapterVoList = planTemplateChapter.getPlanTemplateIntroduceChapterVoList();
            if (!CollectionUtils.isEmpty(planTemplateIntroduceChapterVoList)) {
                for (PlanTemplateIntroduceChapterVo introduceChapter : planTemplateIntroduceChapterVoList) {
                    introduceChapter.setDelete(1);
                }
            }

            planTemplateChapter.setId(copyChapterId);
            planTemplateChapter.setParentId(0L);
            planTemplateChapter.setPlanTemplateId(copyTemplateId);
            planTemplateChapter.setCreateTime(BinaryUtils.getNumberDateTime());
            planTemplateChapter.setModifyTime(BinaryUtils.getNumberDateTime());
            planTemplateChapter.setIntroduceButton(1);
            planTemplateChapterDao.saveOrUpdate(planTemplateChapter);
            BoolQueryBuilder builder = QueryBuilders.boolQuery();
            builder.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
            builder.must(QueryBuilders.termQuery("templateChapterId", chapterId));
            List<PlanTemplateChapterData> planTemplateChapterDataList = planTemplateChapterDataDao.getListByQuery(builder);
            for (PlanTemplateChapterData planTemplateChapterData : planTemplateChapterDataList) {
                long copyChapterDataId = ESUtil.getUUID();
                planTemplateChapterData.setPlanTemplateId(copyTemplateId);
                planTemplateChapterData.setTemplateChapterId(copyChapterId);
                planTemplateChapterData.setId(copyChapterDataId);
                planTemplateChapterData.setCreateTime(BinaryUtils.getNumberDateTime());
                planTemplateChapterData.setModifyTime(BinaryUtils.getNumberDateTime());
                planTemplateChapterDataDao.saveOrUpdate(planTemplateChapterData);
            }
        }
        //下面是调用递归实现子章节和子章节下面data数据的复制
        copyChildChapter(planTemplateChapters,copyTemplateId,copyMap);
    }

    /**
     * 递归实现子章节的复制和内容的复制
     * @param planTemplateChapters
     * @param copyTemplateId
     * @param copyMap
     */
    private void copyChildChapter(List<PlanTemplateChapter> planTemplateChapters, long copyTemplateId, Map<Long, Long> copyMap) {
        Set<Long> chapterFatherIds = copyMap.keySet();
        List<PlanTemplateChapter> planTemplateChapterList = planTemplateChapters.stream().filter(item -> chapterFatherIds.contains(item.getParentId())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(copyMap)) {
            return;
        }
        Map<Long,Long> childMap = new HashMap<>();
        for (PlanTemplateChapter planTemplateChapter : planTemplateChapterList) {
            long copyChapterId = ESUtil.getUUID();
            Long chapterId = planTemplateChapter.getId();
            Long planTemplateId = planTemplateChapter.getPlanTemplateId();
            childMap.put(chapterId,copyChapterId);

            List<PlanTemplateIntroduceChapterVo> planTemplateIntroduceChapterVoList = planTemplateChapter.getPlanTemplateIntroduceChapterVoList();
            if (!CollectionUtils.isEmpty(planTemplateIntroduceChapterVoList)) {
                for (PlanTemplateIntroduceChapterVo introduceChapter : planTemplateIntroduceChapterVoList) {
                    introduceChapter.setDelete(1);
                }
            }

            planTemplateChapter.setId(copyChapterId);
            planTemplateChapter.setPlanTemplateId(copyTemplateId);
            planTemplateChapter.setParentId(copyMap.get(planTemplateChapter.getParentId()));
            planTemplateChapter.setCreateTime(BinaryUtils.getNumberDateTime());
            planTemplateChapter.setModifyTime(BinaryUtils.getNumberDateTime());
            planTemplateChapter.setIntroduceButton(1);
            planTemplateChapterDao.saveOrUpdate(planTemplateChapter);


            BoolQueryBuilder builder = QueryBuilders.boolQuery();
            builder.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
            builder.must(QueryBuilders.termQuery("templateChapterId", chapterId));
            List<PlanTemplateChapterData> planTemplateChapterDataList = planTemplateChapterDataDao.getListByQuery(builder);
            for (PlanTemplateChapterData planTemplateChapterData : planTemplateChapterDataList) {
                long copyChapterDataId = ESUtil.getUUID();
                planTemplateChapterData.setTemplateChapterId(copyChapterId);
                planTemplateChapterData.setPlanTemplateId(copyTemplateId);
                planTemplateChapterData.setId(copyChapterDataId);
                planTemplateChapterData.setCreateTime(BinaryUtils.getNumberDateTime());
                planTemplateChapterData.setModifyTime(BinaryUtils.getNumberDateTime());
                planTemplateChapterDataDao.saveOrUpdate(planTemplateChapterData);
            }
        }
        copyChildChapter(planTemplateChapters,copyTemplateId,childMap);

    }

    private List<PlanTemplateChapter> findAllPlanTemplateChapter(Long templateId) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //boolQueryBuilder.must(QueryBuilders.termQuery("parentId", 0));
        boolQueryBuilder.must(QueryBuilders.termQuery("planTemplateId",templateId));
        boolQueryBuilder.must(QueryBuilders.termQuery("status", 1));
        return planTemplateChapterDao.getListByQuery(boolQueryBuilder);
    }

    @Override
    public TemplateType getTemplateTypeByName(String templateTypeName) {
        TemplateType cdt = new TemplateType();
        cdt.setTypeName(templateTypeName);
        List<TemplateType> results = templateTypeDao.getListByCdt(cdt);
        return CollectionUtils.isEmpty(results) ? null : results.get(0);
    }

    @Override
    public List<TemplateType> getTemplateTypeByIds(List<Long> ids) {
        TermsQueryBuilder queryBuilder = QueryBuilders.termsQuery("id", ids);
        return templateTypeDao.getListByQuery(queryBuilder);
    }
}
